package com.itjin.health.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itjin.health.domain.dto.InjuryReportAddRequest;
import com.itjin.health.domain.dto.InjuryReportUpdateRequest;
import com.itjin.health.domain.entity.InjuryReport;
import com.itjin.health.domain.entity.OfflineAssessmentAppointment;
import com.itjin.health.domain.entity.OnlineAssessmentAppointment;
import com.itjin.health.domain.entity.User;
import com.itjin.health.domain.vo.InjuryReportVO;
import com.itjin.health.domain.vo.InjuryReportDetailVO;
import com.itjin.health.exception.BusinessException;
import com.itjin.health.exception.ErrorCode;
import com.itjin.health.mapper.InjuryReportMapper;
import com.itjin.health.mapper.UserMapper;
import com.itjin.health.mapper.OfflineAssessmentAppointmentMapper;
import com.itjin.health.mapper.OnlineAssessmentAppointmentMapper;
import com.itjin.health.service.InjuryReportService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.beans.BeanUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
import java.util.stream.Collectors;

@Service
@Slf4j
public class InjuryReportServiceImpl extends ServiceImpl<InjuryReportMapper, InjuryReport>
    implements InjuryReportService {

  @Resource
  private UserMapper userMapper;

  @Resource
  private OfflineAssessmentAppointmentMapper offlineAssessmentAppointmentMapper;

  @Resource
  private OnlineAssessmentAppointmentMapper onlineAssessmentAppointmentMapper;

  @Override
  public Integer addInjuryReport(InjuryReportAddRequest injuryReportAddRequest, Integer userId) {
    if (injuryReportAddRequest == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 检查用户是否存在
    User user = userMapper.selectById(userId);
    if (user == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在");
    }

    // 校验参数
    String title = injuryReportAddRequest.getTitle();
    String severity = injuryReportAddRequest.getSeverity();
    if (title == null || title.isEmpty()) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "标题不能为空");
    }
    if (severity == null || severity.isEmpty()) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "严重程度不能为空");
    }

    // 创建伤病报告实体
    InjuryReport injuryReport = new InjuryReport();
    BeanUtil.copyProperties(injuryReportAddRequest, injuryReport);

    // 处理标签
    if (injuryReportAddRequest.getTags() != null) {
      injuryReport.setTags(JSONUtil.toJsonStr(injuryReportAddRequest.getTags()));
    }

    // 如果没有设置受伤时间，则设置为当前时间
    if (injuryReport.getInjuryTime() == null) {
      injuryReport.setInjuryTime(LocalDateTime.now());
    }

    // 设置用户ID和初始状态
    injuryReport.setUserId(userId);
    injuryReport.setStatus("新提交");

    // 保存到数据库
    boolean result = this.save(injuryReport);
    if (!result) {
      throw new BusinessException(ErrorCode.SYSTEM_ERROR, "添加伤病报告失败");
    }

    return injuryReport.getId();
  }

  @Override
  public boolean updateInjuryReport(InjuryReportUpdateRequest injuryReportUpdateRequest, Integer userId) {
    if (injuryReportUpdateRequest == null || injuryReportUpdateRequest.getId() == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 获取伤病报告
    Integer reportId = injuryReportUpdateRequest.getId();
    InjuryReport injuryReport = this.getById(reportId);
    if (injuryReport == null) {
      throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "伤病报告不存在");
    }

    // 校验权限
    if (!injuryReport.getUserId().equals(userId)) {
      throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限修改他人的伤病报告");
    }

    // 校验状态
    if (!"新提交".equals(injuryReport.getStatus())) {
      throw new BusinessException(ErrorCode.OPERATION_ERROR, "只能修改状态为'新提交'的伤病报告");
    }

    // 更新伤病报告
    BeanUtil.copyProperties(injuryReportUpdateRequest, injuryReport);

    // 处理标签
    if (injuryReportUpdateRequest.getTags() != null) {
      injuryReport.setTags(JSONUtil.toJsonStr(injuryReportUpdateRequest.getTags()));
    }

    // 如果更新请求中包含受伤时间，则更新
    if (injuryReportUpdateRequest.getInjuryTime() != null) {
      injuryReport.setInjuryTime(injuryReportUpdateRequest.getInjuryTime());
    }

    // 保存到数据库
    return this.updateById(injuryReport);
  }

  @Override
  public boolean deleteInjuryReport(Integer id, Integer userId) {
    if (id == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 获取伤病报告
    InjuryReport injuryReport = this.getById(id);
    if (injuryReport == null) {
      throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "伤病报告不存在");
    }

    // 校验权限
    if (!injuryReport.getUserId().equals(userId)) {
      throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限删除他人的伤病报告");
    }

    // 校验状态
    if (!"新提交".equals(injuryReport.getStatus())) {
      throw new BusinessException(ErrorCode.OPERATION_ERROR, "只能删除状态为'新提交'的伤病报告");
    }

    // 从数据库中删除
    return this.removeById(id);
  }

  @Override
  public InjuryReportVO getInjuryReportById(Integer id) {
    if (id == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 获取伤病报告
    InjuryReport injuryReport = this.getById(id);
    if (injuryReport == null) {
      throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "伤病报告不存在");
    }

    // 转换为视图对象
    return getInjuryReportVO(injuryReport);
  }

  @Override
  public Page<InjuryReportVO> listAllInjuryReports(long current, long size, String keyword,
      String startDate, String endDate, String severity, String status) {
    // 创建分页对象
    Page<InjuryReport> page = new Page<>(current, size);

    // 构建查询条件
    QueryWrapper<InjuryReport> queryWrapper = new QueryWrapper<>();

    // 关键词搜索（搜索标题、描述和部位）
    if (keyword != null && !keyword.isEmpty()) {
      queryWrapper.and(wrapper -> wrapper
          .like("title", keyword)
          .or()
          .like("description", keyword)
          .or()
          .like("body_part", keyword));
    }

    // 时间范围筛选
    if (startDate != null && !startDate.isEmpty()) {
      queryWrapper.ge("injury_time", startDate);
    }
    if (endDate != null && !endDate.isEmpty()) {
      queryWrapper.le("injury_time", endDate);
    }

    // 严重程度筛选
    if (severity != null && !severity.isEmpty()) {
      queryWrapper.eq("severity", severity);
    }

    // 状态筛选
    if (status != null && !status.isEmpty()) {
      queryWrapper.eq("status", status);
    }

    // 按创建时间降序排序
    queryWrapper.orderByDesc("created_at");

    // 执行分页查询
    Page<InjuryReport> reportPage = this.page(page, queryWrapper);

    // 创建结果分页对象
    Page<InjuryReportVO> resultPage = new Page<>(
        reportPage.getCurrent(),
        reportPage.getSize(),
        reportPage.getTotal());

    // 转换为视图对象列表
    List<InjuryReportVO> reportVOList = new ArrayList<>();
    for (InjuryReport report : reportPage.getRecords()) {
      reportVOList.add(getInjuryReportVO(report));
    }

    resultPage.setRecords(reportVOList);
    return resultPage;
  }

  @Override
  public InjuryReportVO getInjuryReportVO(InjuryReport injuryReport) {
    if (injuryReport == null) {
      return null;
    }

    InjuryReportVO injuryReportVO = new InjuryReportVO();
    BeanUtil.copyProperties(injuryReport, injuryReportVO);

    // 如果字段名不同，确保手动设置
    injuryReportVO.setEvaluationType(injuryReport.getEvaluationType());

    // 处理标签
    if (injuryReport.getTags() != null && !injuryReport.getTags().isEmpty()) {
      injuryReportVO.setTags(JSONUtil.toList(injuryReport.getTags(), String.class));
    }

    // 获取用户名
    User user = userMapper.selectById(injuryReport.getUserId());
    if (user != null) {
      injuryReportVO.setUsername(user.getUsername());
      injuryReportVO.setStudentNumber(user.getStudentNumber());
    }

    return injuryReportVO;
  }

  @Override
  public InjuryReportDetailVO getInjuryReportDetail(Integer id) {
    if (id == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 获取伤病报告基本信息
    InjuryReport report = this.getById(id);
    if (report == null) {
      throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "伤病报告不存在");
    }

    // 转换为DetailVO
    InjuryReportDetailVO detailVO = new InjuryReportDetailVO();
    BeanUtils.copyProperties(report, detailVO);

    // 处理字段名不一致的情况
    detailVO.setEvaluationType(report.getEvaluationType());

    // 获取并设置用户信息
    User user = userMapper.selectById(report.getUserId());
    if (user != null) {
      detailVO.setUsername(user.getUsername());
      detailVO.setStudentNumber(user.getStudentNumber());
    }

    // 根据评估类型查询相应的预约信息
    if ("线下评估".equals(report.getEvaluationType())) {
      // 查询线下预约信息
      QueryWrapper<OfflineAssessmentAppointment> queryWrapper = new QueryWrapper<>();
      queryWrapper.eq("report_id", id);
      OfflineAssessmentAppointment appointment = offlineAssessmentAppointmentMapper.selectOne(queryWrapper);
      detailVO.setOfflineAppointment(appointment);
    } else if ("线上评估".equals(report.getEvaluationType())) {
      // 查询线上预约信息
      QueryWrapper<OnlineAssessmentAppointment> queryWrapper = new QueryWrapper<>();
      queryWrapper.eq("report_id", id);
      OnlineAssessmentAppointment appointment = onlineAssessmentAppointmentMapper.selectOne(queryWrapper);
      detailVO.setOnlineAppointment(appointment);
    }

    return detailVO;
  }

  @Override
  public boolean addDiagnosisAndTreatment(Integer reportId, String diagnosis,
      String treatment, String status, Integer userId) {
    if (reportId == null || diagnosis == null || treatment == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 检查用户是否存在（教师或管理员）
    User user = userMapper.selectById(userId);
    if (user == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在");
    }

    // TODO: 校验用户角色是否为教师或管理员

    // 获取伤病报告
    InjuryReport report = this.getById(reportId);
    if (report == null) {
      throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "伤病报告不存在");
    }

    // 更新诊断和治疗建议
    report.setDiagnosisResult(diagnosis);
    report.setTreatmentSuggestion(treatment);

    // 更新状态（如果提供）
    if (status != null) {
      report.setStatus(status);
    } else {
      // 默认更新为"处理中"状态
      report.setStatus("处理中");
    }

    // 记录诊断人ID
    report.setDiagnosisUserId(userId);

    // 设置诊断时间
    report.setDiagnosisTime(LocalDateTime.now());

    // 保存到数据库
    return this.updateById(report);
  }

  @Override
  public Object getInjuryReportStats(String startDate, String endDate) {
    // 构建查询条件
    QueryWrapper<InjuryReport> queryWrapper = new QueryWrapper<>();

    // 时间范围筛选
    if (startDate != null && !startDate.isEmpty()) {
      queryWrapper.ge("injury_time", startDate);
    }
    if (endDate != null && !endDate.isEmpty()) {
      queryWrapper.le("injury_time", endDate);
    }

    // 获取所有符合条件的伤病报告
    List<InjuryReport> reports = this.list(queryWrapper);

    // 统计数据
    int totalCount = reports.size();

    // 按严重程度统计
    Map<String, Integer> severityStats = new HashMap<>();

    // 按身体部位统计
    Map<String, Integer> bodyPartStats = new HashMap<>();

    // 按状态统计
    Map<String, Integer> statusStats = new HashMap<>();

    // 按月份统计伤病数量
    Map<String, Integer> monthlyStats = new HashMap<>();

    for (InjuryReport report : reports) {
      // 严重程度统计
      String severity = report.getSeverity();
      severityStats.put(severity, severityStats.getOrDefault(severity, 0) + 1);

      // 身体部位统计
      String bodyPart = report.getBodyPart();
      if (bodyPart != null && !bodyPart.isEmpty()) {
        bodyPartStats.put(bodyPart, bodyPartStats.getOrDefault(bodyPart, 0) + 1);
      }

      // 状态统计
      String status = report.getStatus();
      statusStats.put(status, statusStats.getOrDefault(status, 0) + 1);

      // a月份统计
      if (report.getInjuryTime() != null) {
        String month = report.getInjuryTime().getYear() + "-" + report.getInjuryTime().getMonthValue();
        monthlyStats.put(month, monthlyStats.getOrDefault(month, 0) + 1);
      }
    }

    // 构建返回结果
    Map<String, Object> result = new HashMap<>();
    result.put("totalCount", totalCount);
    result.put("severityStats", severityStats);
    result.put("bodyPartStats", bodyPartStats);
    result.put("statusStats", statusStats);
    result.put("monthlyStats", monthlyStats);

    return result;
  }

  @Override
  public String exportInjuryReports(String ids, String startDate, String endDate, String severity) {
    List<InjuryReport> reportList;

    // 如果提供了ID列表，则导出指定ID的伤病报告
    if (ids != null && !ids.isEmpty()) {
      List<Integer> idList = Arrays.stream(ids.split(","))
          .map(Integer::parseInt)
          .collect(Collectors.toList());
      reportList = this.listByIds(idList);
    } else {
      // 否则，按条件导出
      QueryWrapper<InjuryReport> queryWrapper = new QueryWrapper<>();

      // 时间范围筛选
      if (startDate != null && !startDate.isEmpty()) {
        queryWrapper.ge("injury_time", startDate);
      }
      if (endDate != null && !endDate.isEmpty()) {
        queryWrapper.le("injury_time", endDate);
      }

      // 严重程度筛选
      if (severity != null && !severity.isEmpty()) {
        queryWrapper.eq("severity", severity);
      }

      reportList = this.list(queryWrapper);
    }

    // 如果没有符合条件的数据
    if (reportList.isEmpty()) {
      throw new BusinessException(ErrorCode.OPERATION_ERROR, "没有符合条件的数据可导出");
    }

    try {
      // 生成文件名（时间戳）
      String fileName = "injury_reports_" + System.currentTimeMillis() + ".xlsx";

      // 文件保存路径
      String filePath = "export/" + fileName;

      // TODO: 实现导出到Excel文件的具体逻辑
      // 例如：使用POI或EasyExcel等库将数据写入Excel文件

      // 模拟导出成功，返回下载链接
      String downloadUrl = "/api/download/" + fileName;

      log.info("导出伤病报告成功，文件路径：{}", filePath);

      return downloadUrl;
    } catch (Exception e) {
      log.error("导出伤病报告失败", e);
      throw new BusinessException(ErrorCode.SYSTEM_ERROR, "导出失败：" + e.getMessage());
    }
  }

  @Override
  public Page<InjuryReportVO> listUserInjuryReports(Integer userId, long current, long size) {
    // 创建分页对象
    Page<InjuryReport> page = new Page<>(current, size);

    // 构建查询条件
    QueryWrapper<InjuryReport> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("user_id", userId);
    queryWrapper.orderByDesc("created_at");

    // 执行分页查询
    Page<InjuryReport> injuryReportPage = this.page(page, queryWrapper);

    // 创建结果分页对象
    Page<InjuryReportVO> resultPage = new Page<>(
        injuryReportPage.getCurrent(),
        injuryReportPage.getSize(),
        injuryReportPage.getTotal());

    // 转换为视图对象列表
    List<InjuryReportVO> injuryReportVOList = new ArrayList<>();
    for (InjuryReport injuryReport : injuryReportPage.getRecords()) {
      injuryReportVOList.add(getInjuryReportVO(injuryReport));
    }

    resultPage.setRecords(injuryReportVOList);
    return resultPage;
  }
}